/*
 * Copyright (C) 2010 TTPASI, Inc. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS-IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package ttpasi.jgenere.initial_port;

import static ttpasi.jgenere.initial_port.Utils.Aa;
import static ttpasi.jgenere.initial_port.Utils.fixAndMakePositive;
import static ttpasi.jgenere.initial_port.Utils.isAlpha;
import static ttpasi.jgenere.initial_port.Utils.lower;

/**
 * Java port of Caesar cipher from PyGenere v 0.3.  See pygenere.py to learn  
 * more about the original PyGenere implementation, including author contact 
 * information and licensing and use terms.
 * <p/>
 * Caesar objects can encipher and decipher English alphabet text messages.  See 
 * <a target="_blank" href="http://en.wikipedia.org/wiki/Caesar_cipher">http://en.wikipedia.org/wiki/Caesar_cipher</a> 
 * for more information on how the Caesar cipher works.
 * <p/>
 * Caesar objects are immutable. Calls to the encryption algorithms encipher and 
 * decipher return new Caesar objects with the internal message shifted as 
 * specified.
 * <p/>
 * This typical use sequence to encrypt a message
 * <pre>
 * String plaintext = "The quick brown fox jumps over the lazy dog.";
 * Caesar caesar = new Caesar(plaintext);
 * String ciphertext = caesar.encipher(5).text();
 * System.out.println(ciphertext);
 * </pre>
 * outputs
 * <pre>
 * Ymj vznhp gwtbs ktc ozrux tajw ymj qfed itl.
 * </pre>
 * This typical use sequence to decrypt a message
 * <pre>
 * String ciphertext = "Ymj vznhp gwtbs ktc ozrux tajw ymj qfed itl.";
 * Caesar caesar = new Caesar(ciphertext);
 * String plaintext = caesar.decipher(5).text();
 * System.out.println(plaintext);
 * </pre>
 * outputs
 * <pre>
 * The quick brown fox jumps over the lazy dog.
 * </pre>
 * See test source code for further example uses. 
 * <p/>
 * Note: While the cryptography implementations in jgenere.initial_port work 
 * correctly according to the provided test cases, they were not optimized or 
 * otherwise designed to make use of Java language and platform features.  They 
 * are simple ports of the original Python implementation of PyGenere, provided 
 * for academic purposes.  Visit the project web site at 
 * <a target="_blank" href="http://code.google.com/p/jgenere/">http://code.google.com/p/jgenere/</a> 
 * for preferred Java-based implementations of these cryptography algorithms.
 * <p/>
 * The original PyGenere v 0.3 Caesar code:
 * <pre>
 * class Caesar(str):
 * 
 *   """An implementation of the Caesar cipher."""
 * 
 *   def encipher(self, shift):
 *       """Encipher input (plaintext) using the Caesar cipher and return it
 *          (ciphertext)."""
 *       ciphertext = []
 *       for p in self:
 *           if p.isalpha():
 *               ciphertext.append(chr((ord(p) - ord('Aa'[int(p.islower())]) +
 *               shift) % 26 + ord('Aa'[int(p.islower())])))
 *           else:
 *               ciphertext.append(p)
 *       return Caesar(''.join(ciphertext))
 * 
 *   def decipher(self, shift):
 *       """Decipher input (ciphertext) using the Caesar cipher and return it
 *          (plaintext)."""
 *       return self.encipher(-shift)
 * </pre>
 * 
 * @author  Bruce [com.gmail @ ProgrammerBruce]
 * @version 2010.1105
 */
public class Caesar
{
  /**
   * The internal text message to be enciphered or deciphered.
   */
  private final String _text;

  /**
   * Constructs a new Caesar with a text message to be enciphered or deciphered.
   * 
   * @param text The text message to encipher or decipher.
   */
  public Caesar(String text)
  {
    if (text == null)
    {
      text = "";
    }
    _text = text;
  }

  /**
   * Enciphers (i.e., encrypts) the internal text message, shifted by the amount 
   * specified.
   * 
   * @param     shift Distance along English alphabet to shift the message.
   * @return    New Caesar object with the enciphered message.
   */
//def encipher(self, shift):
  public Caesar encipher(int shift)
  {
    shift = fixAndMakePositive(shift);
//  ciphertext = []
    StringBuilder ciphertext = new StringBuilder(_text.length());
    char[] text = _text.toCharArray();
//  for p in self:
    for (char p : text)
    {
//    if p.isalpha():
      if (isAlpha(p))
      {
//      ciphertext.append(
        ciphertext.append(
//             chr(
            (char)(
//            (  ord(p) -   ord('Aa'[  int( p.islower( ))]) + shift)
              ((int)(p) - (int)( Aa [(int)(     lower(p))]) + shift)
//            % 26 +   ord('Aa'[  int( p.islower( ))])
              % 26 + (int)( Aa [(int)(     lower(p))])
//          )
            )
//      )
        );
      }
//    else:
      else
      {
//      ciphertext.append(p)
        ciphertext.append(p);
      }
    }
//  return Caesar(''.join(ciphertext))
    return new Caesar(ciphertext.toString());
  }

  /**
   * Deciphers (i.e., decrypts) the internal text message, backshifted (i.e., 
   * backwards shifted) by the amount specified.
   * 
   * @param     backshift Distance along English alphabet to backwards shift the 
   *            message.
   * @return    New Caesar object with the deciphered message.
   */
//def decipher(self, shift):
  public Caesar decipher(int backshift)
  {
    backshift = fixAndMakePositive(backshift);
//  return self.encipher(-shift)
    return encipher(-1 * backshift);
  }

  /**
   * Retrieves the internal English alphabet text message.
   * 
   * @return The internal English alphabet text message.
   */
  public String text()
  {
    return _text;
  }

  /**
   * Retrieves the internal English alphabet text message.  Same behavior as 
   * {@link #text()}.
   * 
   * @return The internal English alphabet text message.
   */
  @Override
  public String toString()
  {
    return _text;
  }
}
